/***************************************************************************************** 
*                                     TinyRtos51 
*                                The Real-Time Kernel 
*                              Copyright(c) 2024 fanxsp
*                         SPDX-License-Identifier: APACHE-2.0
*       This software is subject to an open source license and is distributed by fanxsp,
*       pursuant to the terms of the Apache License.
******************************************************************************************/
/******************************************************************************************* 
* 				main.c文件
* Author: fanxsp 
* Revision: 1.00
* Date: 2023-05-03
* 	1. 在tinyrtos51cfg.h 中配置 OS
*   2. 在port.h port_xxx.h中适配不同型号的 MCU
*   3. 在option的c51中的预定义宏中定义目标MCU型号
*   4. 如果使能定时服务，需要在一个定时器中调用OSTimeTick()函数，定时中断应设为最低优先级
********************************************************************************************/

/*************  功能说明    ****************************************************************
* 本例程基于STC8H8K64U核心实验板（开天斧）进行编写测试。
* 程序演示跑马灯效果，输出低驱动LED。
* 下载时, 选择时钟 24MHZ (用户可自行修改频率)。
* 按键P32 循环改变跑马灯的频率
* 测试目的：任务切换、任务挂起、任务恢复、任务延时
********************************************************************************************/
#include "tinyRtos51.h"

#define MAIN_Fosc       24000000L   
#define Timer0_Reload   (65536UL -(MAIN_Fosc / 1000))       //Timer0 中断频率 1000次/秒

/* 任务定义 -------------------------------------------------------------------------------*/
/* 任务堆栈  */
OStypeInt8u OSLOC_STACKS taskStack0[30] ;
OStypeInt8u OSLOC_STACKS taskStack1[30] ;
/* 任务ID  */
#define ID_TASK0  0
#define ID_TASK1  1
/* 任务优先级 */
#define PRIO_TASK0  5
#define PRIO_TASK1  6
/* 任务函数原型 */
void Task0(void) ;
void Task1(void) ;
/*-----------------------------------------------------------------------------------------*/

void Init(void) ;
unsigned char t = 2 ;
unsigned char mode = 1;
unsigned char oldKey = 0;

#define KEY1	1
#define KEY2 	2
#define KEY3  3

void main(void)
{
/* OS初始化  */
	OSInit() ;
	
/* 创建任务、二值信号量、计数信号量、事件标志、消息队列  放在这里 */
	OSCreateTask(ID_TASK0,Task0,taskStack0,PRIO_TASK0) ;
	OSCreateTask(ID_TASK1,Task1,taskStack1,PRIO_TASK1) ;

/*----------------------------------------------------------------------------------------*/
	
/* 用户初始化 放在这里  */
	Init() ;
/*----------------------------------------------------------------------------------------*/
	
/* 启动OS */ 
	OSStart() ;
}

/* LED控制任务  */
void Task0(void)
{
	for(;;)
	{
		if(mode == 1) {
			P35 = 0;		//LED On
			OSDelay(t) ;    // 任务延时
			P35 = 1;		//LED Off
			P36 = 0;		//LED On
			OSDelay(t) ;
			P36 = 1;		//LED Off
			P37 = 0;		//LED On
			OSDelay(t) ;
			P37 = 1;		//LED Off
		} else if (mode == 2) {
			P37 = 0;
			OSDelay(t) ;    // 任务延时
			P37 = 1;
			P36 = 0;		//LED On
			OSDelay(t) ;
			P36 = 1;		//LED Off
			P35 = 0;		//LED On
			OSDelay(t) ;    // 任务延时
			P35 = 1;		//LED Off
		} else {
			P35 = 0;
			P36 = 0;
			P37 = 0;
			OSDelay(t) ;    // 任务延时
			P35 = 1;
			P36 = 1;
			P37 = 1;
			OSDelay(t) ;    // 任务延时
			
		}
		
		
	}
}

/* 按键检测 任务 */
void Task1(void)
{
	static unsigned char Key1Cnt ;
	unsigned char newKey;
	for(;;)
	{
		if(!P64 || !P65 || !P66)
		{
			if(!P64) {
				newKey = KEY1;
			} else if (!P65) {
				newKey = KEY2;
			} else {
				newKey = KEY3;
			}
			
			if(oldKey != newKey) {
				Key1Cnt = 1;
				oldKey = newKey;
			}
			
			if(Key1Cnt < 0xff) Key1Cnt ++ ;
		}
		else
		{
			Key1Cnt = 0 ;
		}
		
		if(Key1Cnt == 250)
		{
			OSEnterCritical() ;
			mode = newKey;
			OSExitCritical() ;
		}
		
		OSTaskSuspend() ;  // 任务挂起
	}
}

void ISR_Timer0(void) interrupt 1  // 1ms 中断函数
{
	OSIntResume(ID_TASK1) ;  // 恢复任务
	OSTimeTick() ;    // OS节拍处理
}

void Init(void)
{
	P_SW2 |= 0x80;     //扩展寄存器(XFR)访问使能
	P0M1 = 0x00;   P0M0 = 0x00;   //设置为准双向口
	P1M1 = 0x00;   P1M0 = 0x00;   //设置为准双向口
	P2M1 = 0x00;   P2M0 = 0x00;   //设置为准双向口
	P3M1 = 0x00;   P3M0 = 0x00;   //设置为准双向口
	P4M1 = 0x00;   P4M0 = 0x00;   //设置为准双向口
	P5M1 = 0x00;   P5M0 = 0x00;   //设置为准双向口
	P6M1 = 0x00;   P6M0 = 0x00;   //设置为准双向口
	P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
	
	AUXR = 0x80;    //Timer0 1T, 16 bits 自动重装载模式 
	TH0 = (unsigned char)(Timer0_Reload / 256);
	TL0 = (unsigned char)(Timer0_Reload % 256);
	ET0 = 1;    //Timer0 中断使能
	TR0 = 1;    //Tiner0 开
}

